﻿Imports SNCS
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports System.Runtime.InteropServices
Imports SNCS.RemoteableObject


<Serializable()>
  <ComDefaultInterface(GetType(iClient)), ClassInterface(ClassInterfaceType.None)>
  <ComSourceInterfaces(GetType(iClient))>
Public Class Client
  Implements iClient

  ''' <summary>
  ''' Die lokale Instanz, des RemoteObjekts
  ''' </summary>
  ''' <remarks></remarks>
  Private _remoteObject As MyRemotableObject
  Private _Name As String = String.Empty
  Private _Value As String = String.Empty
  Private _DB As String = String.Empty
  Private _Server As String = "localhost"
  Private _Port As Integer = 12345
  Public Property Name As String Implements iClient.Name
    Get
      Return _Name
    End Get
    Set(value As String)
      _Name = value
    End Set
  End Property

  Public Property Value As String Implements iClient.Value
    Get
      Return _Value
    End Get
    Set(value As String)
      _Value = value
    End Set
  End Property

  Public Property DB As String Implements iClient.DB
    Get
      Return _DB
    End Get
    Set(value As String)
      _DB = value
    End Set
  End Property

  Public Property Server As String Implements iClient.Server
    Get
      Return _Server
    End Get
    Set(value As String)
      _Server = value
    End Set
  End Property

  Public Property Port As Integer Implements iClient.Port
    Get
      Return _Port
    End Get
    Set(value As Integer)
      _Port = value
    End Set
  End Property



  Public Sub New()
  End Sub

  'Public Sub Test()
  '  'Hier wird durch die Methode SetMessage, bereits am Server auseführt.
  '  _remoteObject.SetValue(_Token, "Test", "Test")
  '  MsgBox(_remoteObject.GetValue("Test"))
  'End Sub

  ''' <summary>
  ''' Kann verwendet werden, um die Laufzeit eines Singleton-Objekts aktiv zu verlängern.
  ''' </summary>
  ''' <param name="Time"></param>
  ''' <remarks></remarks>
  Private Sub ExtendRemotingLifetime(ByVal Time As TimeSpan)
    DirectCast(RemotingServices.GetLifetimeService(_remoteObject), Lifetime.ILease).Renew(Time)
  End Sub

  Public Function DelValue(Name As String) As Boolean Implements iClient.DelValue
    Return _remoteObject.DelValue(_Token, Name)
  End Function

  Public Function GetValue(Name As String) As String Implements iClient.GetValue
    Return _remoteObject.GetValue(Name)
  End Function

  Public Function SetValue(Name As String, Value As String) As Boolean Implements iClient.SetValue
    Return _remoteObject.SetValue(_Token, Name, Value)
  End Function

  Public Sub Close() Implements iClient.Close
    If chan.Connected Then
      Revoke()
    End If
    chan.Detach()
    _remoteObject = Nothing
  End Sub

  Dim chan As ClientChannel = ClientChannel.GetInstance
  Private _ConnectedServer As String
  Private _ConnectedServerPort As Integer
  Private _Token As String

  Public Function Connect(Optional server As String = "localhost", Optional port As Integer = 12345, Optional ByVal ServiceName As String = "SNCS") As Boolean Implements iClient.Connect
    Try
      'Hier wird ein neuer TcpChannel ohne vorgegebenen Port erstellt, um eine Kommunikation zu ermöglichen.
      chan.Attach(New TcpChannel())

      'Vor der ersten Verwendung muss der Channel registriert werden

      'Hier wird das RemoteObjekt vom Server geholt und in _remoteObject gespeichert.

      _remoteObject = DirectCast(Activator.GetObject(GetType(MyRemotableObject), String.Concat("tcp://", server, ":", port.ToString, "/", ServiceName)), MyRemotableObject)
      _remoteObject.GetValue("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
      _ConnectedServer = server
      _ConnectedServerPort = port
      Return True

    Catch ex As Exception
#If CONFIG = "Debug" Then
      MsgBox(ex.Message)
#Else
      Throw ex
#End If
      Return False
    End Try
  End Function

  Public Function GetDB(ByVal Name As String, Optional ByVal CreateIfNotExist As Boolean = True) As String Implements iClient.GetDB
    Try
      Return _remoteObject.GetDB(Name, CreateIfNotExist).ToString
    Catch ex As NullReferenceException
      Throw ex
    Catch ex As Exception
      Return String.Empty
    End Try
  End Function

  Public Function DelPrivateValue(Identifier As String, Name As String) As Boolean Implements iClient.DelPrivateValue
    Try
      Return _remoteObject.DelPrivateValue(_Token, Guid.Parse(Identifier), Name)
    Catch ex As NullReferenceException
      Throw ex
    Catch ex As Exception
      Throw New ArgumentException("Keine gültige GUID!", "Identifier", ex)
      Return False
    End Try
  End Function

  Public Function GetPrivateValue(Identifier As String, Name As String) As String Implements iClient.GetPrivateValue
    Try
      Return _remoteObject.GetPrivateValue(Guid.Parse(Identifier), Name)
    Catch ex As NullReferenceException
      Throw ex
    Catch ex As Exception
      Throw New ArgumentException("Keine gültige GUID!", "Identifier", ex)
      Return String.Empty
    End Try
  End Function

  Public Function SetPrivateValue(Identifier As String, Name As String, Value As String) As Boolean Implements iClient.SetPrivateValue
    Try
      Return _remoteObject.SetPrivateValue(_Token, Guid.Parse(Identifier), Name, Value)
    Catch ex As NullReferenceException
      Throw ex
    Catch ex As Exception
      Throw New ArgumentException("Keine gültige GUID!", "Identifier", ex)
      Return False
    End Try
  End Function

  Public Function DeleteDB(Name As String) As Boolean Implements iClient.DeleteDB
    Try
      Return _remoteObject.DeleteDB(_Token, Name)
    Catch ex As NullReferenceException
      Throw ex
    Catch ex As Exception
      Return False
    End Try
  End Function

  'Public Function BSPGET() As Integer Implements iClient.BSPGET
  '  Try
  '    If String.IsNullOrWhiteSpace(_Name) Then
  '      Return 1
  '    Else
  '      If String.IsNullOrWhiteSpace(_DB) Then
  '        _Value = _remoteObject.GetValue(_Name)
  '      Else
  '        Try
  '          _Value = _remoteObject.GetPrivateValue(Guid.Parse(_remoteObject.GetDB(_DB)), _Name)
  '        Catch ex As Exception
  '          Return 1
  '        End Try
  '      End If
  '      Return 0
  '    End If
  '  Catch ex As Exception
  '    Return 1
  '  End Try
  'End Function

  'Public Function BSPSET() As Integer Implements iClient.BSPSET
  '  Try
  '    If String.IsNullOrWhiteSpace(_Name) OrElse String.IsNullOrWhiteSpace(_Name) Then
  '      Return 1
  '    Else
  '      If String.IsNullOrWhiteSpace(_DB) Then
  '        If _remoteObject.SetValue(_Name, _Value) Then Return 0 Else Return 1
  '      Else
  '        Try
  '          If _remoteObject.SetPrivateValue(Guid.Parse(_remoteObject.GetDB(_DB)), _Name, _Value) Then Return 0 Else Return 1
  '        Catch ex As Exception
  '          Return 1
  '        End Try
  '      End If
  '      Return 0
  '    End If
  '  Catch ex As Exception
  '    Return 1
  '  End Try
  'End Function

  'Public Function BSPCON() As Integer Implements iClient.BSPCON
  '  Try

  '    'Hier wird ein neuer TcpChannel ohne vorgegebenen Port erstellt, um eine Kommunikation zu ermöglichen.
  '    chan.Attach(New TcpChannel())

  '    'Vor der ersten Verwendung muss der Channel registriert werden

  '    'Hier wird das RemoteObjekt vom Server geholt und in _remoteObject gespeichert.


  '    Dim ServiceName As String = "SNCS"
  '    _remoteObject = DirectCast(Activator.GetObject(GetType(MyRemotableObject), String.Concat("tcp://", _Server, ":", _Port.ToString, "/", ServiceName)), MyRemotableObject)
  '    '_remoteObject.GetValue("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
  '    Return 0
  '  Catch ex As Exception
  '    MsgBox(ex.Message)
  '    Return 1
  '  End Try
  'End Function

  Public ReadOnly Property Connected As Boolean Implements iClient.Connected
    Get
      Try
        _remoteObject.GetValue("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
        Return chan.Connected
      Catch ex As Exception
        Return False
      End Try
      '      Return chan.Connected
    End Get
  End Property

  Public ReadOnly Property ConnectedServer As String Implements iClient.ConnectedServer
    Get
      If Connected Then
        Return _ConnectedServer
      Else
        Return "NONE"
      End If
    End Get
  End Property

  Public ReadOnly Property ConnectedServerPort As Integer Implements iClient.ConnectedServerPort
    Get
      If Connected Then
        Return _ConnectedServerPort
      Else
        Return -1
      End If
    End Get
  End Property

  Public Function ListDBs(Optional Identifier As String = "") As List(Of String) Implements iClient.ListDBs
    Try
      Return _remoteObject.ListDBs(Identifier)
    Catch ex As NullReferenceException
      Throw ex
    Catch ex As Exception
      Return Nothing
    End Try
  End Function

  Public Function ListPrivateValues(Identifier As String, Optional Name As String = "") As Dictionary(Of String, String) Implements iClient.ListPrivateValues
    Try
      Return _remoteObject.ListPrivateValues(Guid.Parse(Identifier), Name)
    Catch ex As NullReferenceException
      Throw ex
    Catch ex As Exception
      Return Nothing
    End Try
  End Function

  Public Function ListValues(Optional Name As String = "") As Dictionary(Of String, String) Implements iClient.ListValues
    Try
      Return _remoteObject.ListValues(Name)
    Catch ex As NullReferenceException
      Throw ex
    Catch ex As Exception
      Return Nothing
    End Try
  End Function

  Public Function Authenticate(Optional user As String = "user", Optional pass As String = "pass") As Boolean Implements iClient.Authenticate
    _Token = _remoteObject.Authenticate(user, pass)
    If String.IsNullOrWhiteSpace(_Token) Then
      Throw New Auxiliary.AuthenticationException("Invalid user or password.")
    End If
    Return False
  End Function

  Public Function Revoke() As Boolean Implements iClient.Revoke
    Return _remoteObject.Revoke(_Token)
  End Function
End Class
